

var SboxTable = new Array();
SboxTable[0] = new Array(0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05);
SboxTable[1] = new Array(0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99);
SboxTable[2] = new Array(0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62);
SboxTable[3] = new Array(0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6);
SboxTable[4] = new Array(0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8);
SboxTable[5] = new Array(0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35);
SboxTable[6] = new Array(0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87);
SboxTable[7] = new Array(0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e);
SboxTable[8] = new Array(0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1);
SboxTable[9] = new Array(0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3);
SboxTable[10] = new Array(0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f);
SboxTable[11] = new Array(0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51);
SboxTable[12] = new Array(0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8);
SboxTable[13] = new Array(0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0);
SboxTable[14] = new Array(0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84);
SboxTable[15] = new Array(0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48);

var CK = new Array(
    0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
    0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
    0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
    0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
    0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
    0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
    0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
    0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
);

var FK = new Array(0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc);
export function isNull(val:any){
    let flag = false
    if(val===null||val===undefined||val===""){
        flag = true
    }
    return flag
}
function rotl(a:number, n:number) {
    return (a << n) | (a >>> (32 - n))
}
function L1(B:number) {
    return B ^ rotl(B, 2) ^ rotl(B, 10) ^ rotl(B, 18) ^ rotl(B, 24);
}
function L2(B:number) {
    return B ^ rotl(B, 13) ^ rotl(B, 23);
    //	return B^(B<<13|B>>>19)^(B<<23|B>>>9);
}
export function sm4encode(message:any){
    let key='8znkq9epO75Onk9Je0GAmA==';
    //获取SM4的16进制值
    const ciphertext=sm4_encode_cbc2(message,key);
    //16进制值转base64值
    // @ts-ignore
    const base64=base64EncodeUint8Array(hexStrToUint8Array(ciphertext.toString()))

    return base64;
}

export function sm4_encode_cbc2(data:any, key:any) {

    var iv = new Array(0x0F0E0D0C, 0x0B0A0908, 0x07060504, 0x03020100);
    var result = new Array();
    key = xorkey(key);
    data = PKCS7_padding_encode2(data);

    for (var x = 0; x < data.length / 16; x += 1) {
        var message = new Array();
        message[0] = (data[x * 16 + 0] << 24) | (data[x * 16 + 1] << 16) | (data[x * 16 + 2] << 8) | (data[x * 16 + 3] << 0)
        message[1] = (data[x * 16 + 4] << 24) | (data[x * 16 + 5] << 16) | (data[x * 16 + 6] << 8) | (data[x * 16 + 7] << 0)
        message[2] = (data[x * 16 + 8] << 24) | (data[x * 16 + 9] << 16) | (data[x * 16 + 10] << 8) | (data[x * 16 + 11] << 0)
        message[3] = (data[x * 16 + 12] << 24) | (data[x * 16 + 13] << 16) | (data[x * 16 + 14] << 8) | (data[x * 16 + 15] << 0)

        var tbc = new Array();
        for (var i = 0; i < iv.length; i++) {
            tbc.push(bigxor(iv[i], message[i]));
        };
        var ciphertext = KJUR_encrypt_sm4(tbc, key, "cbc")
        iv = ciphertext
        result = result.concat(ciphertext);

    }
    //	alert(result);

    var ret :string[]= new Array();

    for (var i = 0; i < result.length; i++) {
        var ri = parseInt(result[i], 16);
        ret.push(((ri >>> 24) & 0xff).toString(16));
        ret.push(((ri >>> 16) & 0xff).toString(16));
        ret.push(((ri >>> 8) & 0xff).toString(16));
        ret.push((ri & 0xff).toString(16));
    }
    //return ret;
    //	alert(ret);
    return bjca_mssp_charArray2Str_sm4(ret);
}
export function xorkey(key:string) {
    var result = new Array();
    for (var i = 0; i < key.length; i += 8) {
        result.push(parseInt(key.slice(i, i + 8), 16))
    }
    return result;
}
export function PKCS7_padding_encode2(data:string) {
    var result = new Array();
    for (var i = 0; i < data.length; i++) {
        result.push(data.charCodeAt(i));
    };
    var size = 16 - result.length % 16
    for (i = 0; i < size; i++) {
        result.push(size)
    };
    return result;
}
function bigxor(a:number, b:number) {
    return a ^ b
}
function KJUR_encrypt_sm4(messsage:any[], key:any, method:any) {
    var MK = key;
    var x = messsage;
    var rk = sm4_getkey(MK);


    for (var i = 0; i < 32; i += 4) {
        //console.log("i=" + i + " rk[i]=" + rk[i]);
        var mid;
        mid = x[1] ^ x[2] ^ x[3] ^ rk[i + 0];
        mid = sm4Sbox(mid);
        x[0] = x[0] ^ L1(mid);   //x4

        mid = x[2] ^ x[3] ^ x[0] ^ rk[i + 1];
        mid = sm4Sbox(mid);
        x[1] = x[1] ^ L1(mid);	//x5

        mid = x[3] ^ x[0] ^ x[1] ^ rk[i + 2];
        mid = sm4Sbox(mid);
        x[2] = x[2] ^ L1(mid);	//x6

        mid = x[0] ^ x[1] ^ x[2] ^ rk[i + 3];
        mid = sm4Sbox(mid);
        x[3] = x[3] ^ L1(mid);	//x7
    };
    var Y = new Array(x[3], x[2], x[1], x[0])
    return Y;
}
function sm4Sbox(a:number) {
    var b1 = SboxTable[(a & 0xf0000000) >>> 28][(a & 0x0f000000) >>> 24]
    var b2 = SboxTable[(a & 0x00f00000) >>> 20][(a & 0x000f0000) >>> 16]
    var b3 = SboxTable[(a & 0x0000f000) >>> 12][(a & 0x00000f00) >>> 8]
    var b4 = SboxTable[(a & 0x000000f0) >>> 4][(a & 0x0000000f) >>> 0]
    return (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4 << 0)
}
function sm4_getkey(MK:any) {
    var K = new Array();
    var rk = new Array();
    K[0] = bigxor(MK[0], FK[0]);
    K[1] = bigxor(MK[1], FK[1]);
    K[2] = bigxor(MK[2], FK[2]);
    K[3] = bigxor(MK[3], FK[3]);

    var mid;
    for (var i = 0; i < 32; i += 4) {
        //K[i+4] = bigxor(K[i], PUT_ULONG_BE(bigxor(bigxor(K[i+1], K[i+2]), bigxor(K[i+3], CK[i]))));

        mid = K[1] ^ K[2] ^ K[3] ^ CK[i + 0];
        mid = sm4Sbox(mid);
        K[0] = K[0] ^ L2(mid);
        rk[i + 0] = K[0];

        mid = K[2] ^ K[3] ^ K[0] ^ CK[i + 1]
        mid = sm4Sbox(mid);
        K[1] = K[1] ^ L2(mid);
        rk[i + 1] = K[1];


        mid = K[3] ^ K[0] ^ K[1] ^ CK[i + 2]
        mid = sm4Sbox(mid);
        K[2] = rk[i + 2] = K[2] ^ L2(mid);
        rk[i + 2] = K[2];

        mid = K[0] ^ K[1] ^ K[2] ^ CK[i + 3]
        mid = sm4Sbox(mid);
        K[3] = K[3] ^ L2(mid);
        rk[i + 3] = K[3];
    };



    return rk;
}

function bjca_mssp_charArray2Str_sm4(arr: string[]) {
    var r = "";
    for (var i = 0; i < arr.length; i++) {
        var d = parseInt(arr[i], 16) & 0xff;

        if (d < 16) {
            r = r + "0";
        }
        r += d.toString(16);

    }
    return r;

}
function hexStrToUint8Array(hexStr) {
    if (!hexStr || hexStr.length % 2 != 0) {
        return null
    }
    var a = [];
    for (var i = 0; i < hexStr.length; i += 2) {
        // @ts-ignore
        a.push(parseInt("0x" + hexStr.substr(i, 2), 16))
    }
    return new Uint8Array(a)
}
function base64EncodeUint8Array(uint8Array) {
    var CHUNK_SIZE = 32768;
    var index = 0;
    var length = uint8Array.length;
    var result = "";
    var slice;
    var slice_tmp = "";
    while (index < length) {
        slice = uint8Array.subarray(index, Math.min(index + CHUNK_SIZE, length));
        for (var i = 0,
                 len = slice.length; i < len; i++) {
            slice_tmp += String.fromCharCode(slice[i])
        }
        result += slice_tmp;
        index += CHUNK_SIZE;
        slice_tmp = ""
    }
    return btoa(result)
}
